#pragma once
/*
    基于msg抽象层实现msg具象层，其中最重要的是对于BaseMessage的派生类进行实现; 以及实现一个消息对象的生产工厂。
*/
#include "detail.hpp"
#include "fields.hpp"
#include "abstract.hpp"
#include <vector>
using std::string;
using std::vector;

namespace tmh_rpc
{
    // 用于设置主机ip和端口
    typedef std::pair<string, int> Address;
    //---------------------------------JsonMessgae 基本消息类---------------------------------------------
    class JsonMessage : public BaseMessage
    // JsonMessage同时也是JsonRequest,JsonResponse的基类
    {
    public:
        using ptr = std::shared_ptr<JsonMessage>;

        // 对于结构化的消息类型和id进行序列化操作
        virtual string serialize() override
        // 对基类的序列化方法进行重写
        {
            // 调用JSON实用工具进行实现
            string body;
            bool ret = JSON::serialize(_body, body);
            if (ret == false)
            {
                return string();
            }
            return body;
        }

        // 对于返回的字符串进行反序列化操作 得到_mtype和_rid
        virtual bool deserialize(const string &msg) override
        // 对基类的反序列化进行重写
        {
            // 调用JSON进行实现
            return JSON::deserialize(msg, _body);
        }

    protected:
        Json::Value _body;
    };
    //--------由JsonMessage 派生出来的 JsonRequest 和 JsonResponse----------------------------------
    // JsonRequest
    class JsonRequest : public JsonMessage
    {
        // Request各个子类中字段差异较大,因此不做检测
    public:
        using ptr = std::shared_ptr<JsonRequest>;
    };

    // JsonResponse
    class JsonResponse : public JsonMessage
    {
        // Response子类中都有rcode字段,因此对rcode进行检测
    public:
        using ptr = std::shared_ptr<JsonResponse>;

        virtual bool check() override
        {
            if (_body[KEY_RCODE].isNull() == true)
            {
                // 响应状态码中缺少Rcode字段
                ELOG("响应中没有响应状态码!");
                return false;
            }

            if (_body[KEY_RCODE].isIntegral() == false)
            {
                // 响应状态码不是数字
                ELOG("响应状态码类型错误!");
                return false;
            }
            return true;
        }
        virtual RCode rcode()
        {
            return (RCode)_body[KEY_RCODE].asInt();
        }

        virtual void setRCode(const RCode &rcode)
        {
            _body[KEY_RCODE] = (int)rcode;
        }
    };

    //-------------由 JsonRequest 派生出来的各个请求类--------------------------------------
    // RpcRequest
    class RpcRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<RpcRequest>;

        // 对请求字段进行检查
        virtual bool check() override
        {
            // 请求字段的方法
            if (_body[KEY_METHOD].isNull() == true || _body[KEY_METHOD].isString() == false)
            {
                ELOG("RPC 请求中没有方法名称或方法名称类型错误!");
                return false;
            }

            // 请求字段的参数
            if (_body[KEY_PARAMETER].isNull() == true || _body[KEY_PARAMETER].isObject() == false)
            {
                ELOG("RPC 请求中没有参数信息或参数信息类型错误!");
                return false;
            }
            return true;
        }

        string method()
        {
            return _body[KEY_METHOD].asString();
        }
        void setMethod(const string &method_name)
        {
            _body[KEY_METHOD] = method_name;
        }

        Json::Value parameter()
        {
            return _body[KEY_PARAMETER];
        }

        void setParameter(const Json::Value &parameter)
        {
            _body[KEY_PARAMETER] = parameter;
        }
    };

    // TopicRequest
    class TopicRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<TopicRequest>;

        // 对请求字段进行检查
        virtual bool check() override
        {
            // 请求字段的主题字段
            if (_body[KEY_TOPIC_KEY].isNull() == true || _body[KEY_TOPIC_KEY].isString() == false)
            {
                ELOG("Topic 请求中没有主题名称或主题名称类型错误!");
                return false;
            }

            // 请求字段的操作类型字段
            if (_body[KEY_OPTYPE].isNull() == true || _body[KEY_OPTYPE].isIntegral() == false)
            {
                ELOG("Topic 请求中没有操作类型或操作类型的类型错误!");
                return false;
            }

            // 操作类型为发布 && 发布消息错误
            if (_body[KEY_OPTYPE].asInt() == (int)TopicOptype::TOPIC_PUBLISH &&
                (_body[KEY_TOPIC_MSG].isNull() == true || _body[KEY_TOPIC_MSG].isString() == false))
            {
                ELOG("Topic 消息发布请求中没有消息内容字段或消息内容的类型错误!");
                return false;
            }
            return true;
        }

        // 获取字段信息或进行设置
        string topicKey()
        {
            return _body[KEY_TOPIC_KEY].asString();
        }
        void setTopicKey(const string &key)
        {
            _body[KEY_TOPIC_KEY] = key;
        }

        TopicOptype opType()
        {
            return (TopicOptype)_body[KEY_OPTYPE].asInt();
        }
        
        void setOptype(TopicOptype optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }

        string topicMsg()
        {
            return _body[KEY_TOPIC_MSG].asString();
        }
        void setTopicMsg(const string &msg)
        {
            _body[KEY_TOPIC_MSG] = msg;
        }
    };

    // ServiceRequest

    class ServiceRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<ServiceRequest>;

        // 对Service 请求字段进行检查
        virtual bool check() override
        {
            // 请求字段的方法
            if (_body[KEY_METHOD].isNull() == true || _body[KEY_METHOD].isString() == false)
            {
                ELOG("Service 请求中没有方法名称或方法名称类型错误!");
                return false;
            }

            // 请求字段的操作类型字段
            if (_body[KEY_OPTYPE].isNull() == true || _body[KEY_OPTYPE].isIntegral() == false)
            {
                ELOG("Service 请求中没有操作类型或操作类型的类型错误!");
                return false;
            }

            // 在服务发现请求中, 是不知道主机信息的

            if (_body[KEY_OPTYPE].asInt() != (int)(ServiceOptype::SERVICE_DISCOVERY) &&
                (_body[KEY_HOST].isNull() == true ||
                 _body[KEY_HOST].isObject() == false ||
                 _body[KEY_HOST][KEY_HOST_IP].isNull() == true ||
                 _body[KEY_HOST][KEY_HOST_IP].isString() == false ||
                 _body[KEY_HOST][KEY_HOST_PORT].isNull() == true ||
                 _body[KEY_HOST][KEY_HOST_PORT].isIntegral() == false))
            {
                ELOG("Service 请求中主机地址信息错误!");
                return false;
            }
            return true;
        }

        // 获取字段信息或进行设置
        string method()
        {
            return _body[KEY_METHOD].asString();
        }
        void setMethod(const string &name)
        {
            _body[KEY_METHOD] = name;
        }

        ServiceOptype opType()
        {
            return (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }

      
        void setOptype(ServiceOptype optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }

        Address host()
        {
            Address addr;
            addr.first = _body[KEY_HOST][KEY_HOST_IP].asString();
            addr.second = _body[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }
        void setHost(const Address &host)
        {
            Json::Value val;
            val[KEY_HOST_IP] = host.first;
            val[KEY_HOST_PORT] = host.second;
            _body[KEY_HOST] = val;
        }
    };

    //-------------由 JsonResponse 派生出来的各个响应类--------------------------------------
    // RpcResponse
    class RpcResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<RpcResponse>;

        // 对RPC 响应字段进行检查
        virtual bool check() override
        {
            if (_body[KEY_RCODE].isNull() == true || (_body[KEY_RCODE].isIntegral() == false))
            {
                ELOG("Rpc 响应中没有响应状态码,或响应状态码类型错误!");
                return false;
            }

            if (_body[KEY_RESULT].isNull() == true )
            {
                ELOG("Rpc 响应中没有Rpc调用结果,或结果类型错误!");
                return false;
            }
            return true;
        }

        // 获取响应字段 或对其进行设置

        Json::Value result()
        {
            return _body[KEY_RESULT];
        }

        void setResult(const Json::Value &res)
        {
            _body[KEY_RESULT] = res;
        }
    };

    // TopicResponse
    class TopicResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<TopicResponse>;
    };

    // ServiceResponse
    class ServiceResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<ServiceResponse>;

        // 对Service 响应字段进行检查
        virtual bool check() override
        {
            // 对于不论何种的Service请求，Response都是需要进行rcode检测的
            if (_body[KEY_RCODE].isNull() == true || (_body[KEY_RCODE].isIntegral() == false))
            {
                ELOG("Service 响应中没有响应状态码,或响应状态码类型错误!");
                return false;
            }

            if (_body[KEY_OPTYPE].isNull() == true || (_body[KEY_OPTYPE].isIntegral() == false))
            {
                ELOG("Service 响应中没有操作类型,或操作类型的类型错误!");
                return false;
            }

            // 对于方法发现服务, 需要检测是否有host等字段
            if (_body[KEY_OPTYPE].asInt() == (int)(ServiceOptype::SERVICE_DISCOVERY) &&
                (_body[KEY_METHOD].isNull() == true ||
                 _body[KEY_METHOD].isString() == false ||
                 _body[KEY_HOST].isNull() == true ||
                 _body[KEY_HOST].isArray() == false))
            {
                ELOG("Service 服务发现响应中响应信息字段错误!");
                return false;
            }
            return true;
        }

        // 获取响应字段 或对其进行设置
        // 操作类型
        ServiceOptype opType()
        {
            return (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }

        void setOptype(const ServiceOptype &optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }

        // 方法
        string method()
        {
            return _body[KEY_METHOD].asString();
        }

        void setMethod(const string &method)
        {
            _body[KEY_METHOD] = method;
        }

        // 对于服务注册+上线+下线功能，不需要返回host字段; 但是对于服务发现需要返回提供该服务的主机地址
        vector<Address> hosts()
        {
            vector<Address> addrs;
            int sz = _body[KEY_HOST].size();
            for (int i = 0; i < sz; i++)
            {
                Address addr;
                addr.first = _body[KEY_HOST][i][KEY_HOST_IP].asString();
                addr.second = _body[KEY_HOST][i][KEY_HOST_PORT].asInt();

                addrs.push_back(addr);
            }

            return addrs;
        }

        void setHost(const vector<Address> &addrs)
        {
            for (auto &addr : addrs)
            {
                Json::Value val;
                val[KEY_HOST_IP] = addr.first;
                val[KEY_HOST_PORT] = addr.second;
                _body[KEY_HOST].append(val);
            }
        }
    };
    // end req和res消息类型的封装

    //--------------------------------------- 实现消息对象的生产工厂 -------------------------------------
    class MessageFactory
    {
    public:
        // 父类指针指向子类对象, 构造出来不同的消息对象
        static BaseMessage::ptr create(MType mtype)
        {
            switch (mtype)
            {
            case MType::REQ_RPC:
                return std::make_shared<RpcRequest>();
            case MType::RSP_RPC:
                return std::make_shared<RpcResponse>();

            case MType::REQ_TOPIC:
                return std::make_shared<TopicRequest>();
            case MType::RSP_TOPIC:
                return std::make_shared<TopicResponse>();

            case MType::REQ_SERVICE:
                return std::make_shared<ServiceRequest>();
            case MType::RSP_SERVICE:
                return std::make_shared<ServiceResponse>();
            }

            // 如果以上类型都没有匹配上
            return BaseMessage::ptr();
        }

        // 函数模板进行生产
        template <typename T, typename... Args>
        static std::shared_ptr<T> create(Args &&...args)
        {
            return std::make_shared<T>(std::forward(args)...);
        }
    };
}